package com.imooc.business.context;

import com.google.common.collect.Maps;
import com.imooc.business.RuleBusiness;
import com.imooc.business.domain.Metadata;
import com.imooc.business.domain.Rule;
import com.imooc.business.util.DateUtil;
import com.imooc.infra.repository.jdbc.params.StandardSqlParam;
import com.imooc.module.collect.enums.DimensionEnum;
import com.imooc.module.collect.enums.PeriodEnum;
import com.imooc.module.collect.request.ParamsRequest;
import com.imooc.module.reponse.DataResponse;
import lombok.Data;
import lombok.experimental.Accessors;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.assertj.core.util.Lists;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.checker.units.qual.C;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author Tim
 * @Description:
 * @Version 1.0
 */
@Data
public class DataContext {
    private ParamsRequest request;
    private DataResponse response;

    private CacheModel cacheModel = new CacheModel();

    /**
     * 构建采集参数
     * @return
     */
    public Map<String, Object> buildCollectParams() {
        Map<String, Object> params = Maps.newHashMap();
        ParamsRequest.DimensionParameter dimensionParameter = request.getDimensionParameter();
        List<Long> userIds = dimensionParameter.getUserIds();
        String groupId = dimensionParameter.getGroupId();
        Long schoolId = dimensionParameter.getSchoolId();

        if (CollectionUtils.isNotEmpty(userIds)) {
            params.put(StandardSqlParam.USER_IDS, userIds);
        }
        if (StringUtils.isNotEmpty(groupId)) {
            params.put(StandardSqlParam.GROUP_ID, groupId);
        }
        if (Objects.nonNull(schoolId)) {
            params.put(StandardSqlParam.SCHOOL_ID, schoolId);
        }
        params.put(StandardSqlParam.BUSINESS_ID, cacheModel.getRule().getBusinessId());
        //数据处理的请求时间
        params.put(StandardSqlParam.REQUEST_TIME, DateUtil.formatDate(request.getRequestDate(), StandardSqlParam.DATE_PATTERN));
        //统计时间
        params.put(StandardSqlParam.COUNT_TIME, buildCountTime());
        return params;
    }

    /**
     * 构建初始化采集结果
     * @return
     */
    public List<Map<String, Object>> buildCollectResult() {
        ParamsRequest.DimensionParameter dimension = request.getDimensionParameter();
        Rule rule = cacheModel.getRule();
        List<Metadata> metadatas = rule.getMetadatas();
        Map<String, Object> defaultValues = metadatas.stream().collect(Collectors.toMap(Metadata::getEnName, Metadata::getDefaultValue));

        String groupId = dimension.getGroupId();
        Long schoolId = dimension.getSchoolId();
        if (DimensionEnum.USER.getDimension().equals(dimension.getDimension())) {
           return dimension.getUserIds().stream().map(userId -> buildRow(userId, groupId, schoolId, defaultValues)).collect(Collectors.toList());
        } else if (DimensionEnum.GROUP.getDimension().equals(dimension.getDimension())) {
            return Lists.newArrayList(buildRow(null, groupId, schoolId, defaultValues));
        } else if (DimensionEnum.SCHOLL.getDimension().equals(dimension.getDimension())) {
            return Lists.newArrayList(buildRow(null, null, schoolId, defaultValues));
        }
        return Lists.newArrayList();
    }

    /**
     * 初始化一行结果
     * @param userId
     * @param groupId
     * @param schoolId
     * @param defaultValues
     * @return
     */
    private Map<String, Object> buildRow(Long userId, String groupId, Long schoolId, Map<String, Object> defaultValues) {
        Map<String, Object> row = Maps.newHashMap();

        row.put(StandardSqlParam.COUNT_TIME, buildCountTime());
        row.put(StandardSqlParam.RULE_ID, cacheModel.getRule().getRuleId());
        row.putAll(defaultValues);
        if (Objects.nonNull(userId)) {
            row.put(StandardSqlParam.USER_ID, userId);
        }
        if (StringUtils.isNotEmpty(groupId)) {
            row.put(StandardSqlParam.GROUP_ID, groupId);
        }
        if (Objects.nonNull(schoolId)) {
            row.put(StandardSqlParam.SCHOOL_ID, schoolId);
        }
        return row;
    }

    /**
     * 统计时间范围
     * @return
     */
    private String buildCountTime() {
        return buildCountTime(cacheModel.getPeriod(), request.getStartTime(), request.getEndTime());
    }

    public static String buildCountTime(PeriodEnum period, Date startTime, Date endTime) {
        return switch (period) {
            case DAY -> DateUtil.formatDate(startTime, StandardSqlParam.DATE_PATTERN);
            case WEEK, MONTH, SEMESTER, SCHOOL_YEAR, CUSTOM -> DateUtil.formatDate(startTime, StandardSqlParam.DATE_PATTERN) +"-"+ DateUtil.formatDate(endTime, StandardSqlParam.DATE_PATTERN);
        };
    }

    @Accessors(chain = true)
    @Data
    public static class CacheModel {
        /**
         * 方便获取规则模型
         */
        private Rule rule;
        /**
         * 缓存周期
         */
        private PeriodEnum period;
        /**
         * 缓存维度
         */
        private DimensionEnum dimension;
        /**
         * 缓存计算的中间结果
         */
        private List<Map<String, Object>> results;
    }
}
